#ifndef _DEFS_H_
#define _DEFS_H_

#include "macros.h"
#include "../../include/VarArray.hpp"
#include <algorithm> // max min
#include <cmath>
#include <iostream>
typedef double real_t;

// from su2
// gamma 跟 cmath 中的一个函数命名冲突，故意为 gama
constexpr real_t gama{1.4};
constexpr real_t gam1{0.4};
constexpr real_t rgas_d{287.058};
constexpr real_t cpgas_d{1004.703};
constexpr real_t cvgas_d{717.645};
constexpr real_t Prl{0.72};
constexpr real_t PI{3.1415926535897932};
constexpr real_t RAD{1.7453292519943296e-2};

enum class Equation_t
{
  Euler,
  NavierStokes
};

enum class TimeStep_t
{
  Local,
  Global
};

enum class Nondim_t
{
  FREESTREAM_PRESS_EQ_ONE,
  FREESTREAM_VEL_EQ_MACH,
  FREESTREAM_VEL_EQ_ONE,
  DIMENSIONAL
};

enum class ConvectFlux_t
{
  Roe1,
  Roe2
};

enum class TimeDiscrete_t
{
  RUNGE_KUTTA_EXPLICIT,
  EULER_IMPLICIT
};

enum class Limiter_t
{
  NONE,
  VENKATAKRISHNAN
};

enum class MeshFormat_t
{
  ASSCII,
  Binary
};

enum class OutputFormat_t
{
  Tec_ASSCII,
  Tec_Binary
};
// generic 边界文件格式
enum class Bound_t
{
  NoBoundCond = 0,
  InnerBound = -1,
  Wall = 2,
  Symmetry = 3,
  Farfield = 4,
  Inflow = 5,
  Outflow = 6,
  // periodic = generic_#1
  // Periodic = 8
};
// 检查网格
struct Coord_t
{
  real_t x, y,
#ifdef TEST
      z
#endif
      ;
};

struct Grad_t
{
  real_t ux, uy, vx, vy, Tx, Ty;
#ifdef TEST
  friend std::ostream &operator<<(std::ostream &os, const Grad_t &grad)
  {
    // os << "(" << grad.ux << "," << grad.uy << "," << grad.vx << "," << grad.vy
    //    << "," << grad.Tx << "," << grad.Ty << ")"
    //    << "  ";
    os << grad.ux << "  " << grad.uy << "   " << grad.vx << "  " << grad.vy
       << "  " << grad.Tx << "  " << grad.Ty << "  ";
    return os;
  }
#endif
};

struct Area_t
{
  real_t sx, sy;
#ifdef TEST
  friend std::ostream &operator<<(std::ostream &os, const Area_t &area)
  {
    // os << "(" << area.sx << "," << area.sy << ")"
    //    << "  ";
    os << area.sx << "  " << area.sy
       << "  ";
    return os;
  }
#endif
};

struct ConsVar_t
{
  real_t rho, rhou, rhov, rhoE;
#ifdef TEST
  friend std::ostream &operator<<(std::ostream &os, const ConsVar_t &cons)
  {
    // os << "(" << cons.rho << "," << cons.rhou << "," << cons.rhov << ","
    //    << cons.rhoE << ")"
    //    << "  ";
    os << cons.rho << "  " << cons.rhou << "  " << cons.rhov << "  "
       << cons.rhoE
       << "  ";
    return os;
  }
#endif
};
// 不用担心内存，类中都是资句柄，不分配就不占内存
struct DeptVarE_t
{
  real_t
      // p,
      T,
      c;
#ifdef TEST
  friend std::ostream &operator<<(std::ostream &os, const DeptVarE_t &dept)
  {
    // os << "(" << dept.p << "," << dept.T << "," << dept.c << ")"
    //    << "  ";
    os
        // << dept.p << "  "
        << dept.T << "  " << dept.c
        << "  ";
    return os;
  }
#endif
};

struct DeptVarNS_t
{
  real_t
      // p,
      T,
      c, mu, ka;
#ifdef TEST
  friend std::ostream &operator<<(std::ostream &os, const DeptVarNS_t &dept)
  {
    // os << "(" << dept.p << "," << dept.T << "," << dept.c << "," << dept.mu
    //    << "," << dept.ka << ")"
    //    << "  ";
    os
        // << dept.p << "  "
        << dept.T << "  " << dept.c << "  " << dept.mu
        << "  " << dept.ka
        << "  ";
    return os;
  }
#endif
};

struct BoundDescrp_t
{
  /**
   * @brief Btype 物理边界类型
   *  Bn 边界编号 1 2 3 4
   *  beg 当前边界的起始  以单元编号，不是网格点
   *  end 当前边界的结束
   *  带后缀s 的表示邻接边界，需要从其获取数据的“源方”
   *  lsteps = (begs < ends) ? 1 : -1;
   */
  Bound_t BType;
  int Bn, beg, end, Bns, begs, ends;
  int lsteps, dum1, dum2, ins1, ins2;
  bool isIface, isIfaceAdj;
#ifdef TEST
  friend std::ostream &operator<<(std::ostream &os, BoundDescrp_t &bound)
  {
    os << "("
       // << bound.BType << ","
       << bound.Bn << "," << bound.beg << "," << bound.end << "," << bound.Bns
       << "," << bound.begs << "," << bound.ends << "," << bound.lsteps << ","
       << bound.dum1 << "," << bound.dum2 << "," << bound.ins1 << ","
       << bound.ins2 << "," << bound.isIface << "," << bound.isIfaceAdj << ")"
       << "  ";
    return os;
  }
#endif
};

#endif